﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using NUnit.Framework;
using HP.Cachalote.WPF.Model;
using HP.Cachalote.WPF.ViewModel;
using HP.Cachalote.UnitTests.FakeServices;
using HP.Cachalote.WPF.Shared;
using HP.Cachalote.Services.Shared;

namespace HP.Cachalote.UnitTests.WPFTests
{
    [TestFixture]
    public class InformationFormatterTest
    {
        [SetUp]
        public void Setup() { }

        #region Tests for FormatDueDateDisplay
        [Test]
        public void FormatDueDateDisplayBasedOnEarlierDueDateTest()
        {
            DateTime dueDate = new DateTime(2012, 11, 3);  // Earlier
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = string.Format("{0} Days", dueDate.Subtract(currentDate).Days);
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayBasedOnNullDueDateTest()
        {
            DateTime? dueDate = null;                       // null
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "Set DueDate";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayTodayTest()
        {
            var dueDate = new DateTime(2012, 11, 5);        // Monday
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "Today";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayTomorrowTest()
        {
            var dueDate = new DateTime(2012, 11, 6);        // Tuesday
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "Tomorrow";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplay2DaysBasedOnMondayTest()
        {
            var dueDate = new DateTime(2012, 11, 7);        // Wednesday
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "2 Days";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplay3DaysBasedOnMondayTest()
        {
            var dueDate = new DateTime(2012, 11, 8);        // Thursday
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "3 Days";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayThisWeekBasedOnMondayTest()
        {
            var dueDate = new DateTime(2012, 11, 9);        // Friday
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "This Week";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));

            dueDate = new DateTime(2012, 11, 10);           // Saturday
            actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayNextWeekBasedOnMondayTest()
        {
            var dueDate = new DateTime(2012, 11, 11);       // Next Sunday
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "Next Week";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Next Sunday to this Monday. Expected is {0}. Actual is {1}.", expected, actual));

            dueDate = new DateTime(2012, 11, 13);           // Next Tuesday
            actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Next Tuesday to this Monday. Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayThisMonthBasedOnMondayTest()
        {
            var dueDate = new DateTime(2012, 11, 18);       // Second Sunday
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "This Month";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Second Sunday to this Monday. Expected is {0}. Actual is {1}.", expected, actual));

            dueDate = new DateTime(2012, 11, 30);           // The end of the month
            actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("The end of the month. Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayNextMonthBasedOnMondayTest()
        {
            var dueDate = new DateTime(2012, 12, 18);       // Next Month
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = "Next Month";
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Next Month. Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayParticularDateBasedOnMondayTest()
        {
            var dueDate = new DateTime(2013, 1, 18);
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = string.Format("{0} {1}", dueDate.Day, GeneralUtilities.GetMonthShortName(dueDate.Month));
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Particular Date. Expected is {0}. Actual is {1}.", expected, actual));
        }

        [Test]
        public void FormatDueDateDisplayParticularDaysBasedOnMondayTest()
        {
            var dueDate = new DateTime(2013, 3, 18);
            var currentDate = new DateTime(2012, 11, 5);    // Monday
            var expected = string.Format("{0} Days", dueDate.Subtract(currentDate).Days);
            var actual = InformationFormatter.FormatDueDateDisplay(dueDate, currentDate);

            Assert.AreEqual(expected, actual, string.Format("Days left. Expected is {0}. Actual is {1}.", expected, actual));
        }
        #endregion

        #region Tests for GetDueDateStatus
        [Test]
        public void GetDueDateStatusNotStartedWithoutDueDateTest()
        {
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.NotStarted;
            var actual = InformationFormatter.GetDueDateStatus(null, null, null, currentDate);

            Assert.AreEqual(expected, actual, "NotStarted without DueDate");
        }

        [Test]
        public void GetDueDateStatusNotStartedWithDueDateTest()
        {
            var dueDate = new DateTime(2012, 11, 25);                       // 2012-11-25
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.NotStarted;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, null, null, currentDate);

            Assert.AreEqual(expected, actual, "NotStarted with DueDate");
        }

        [Test]
        public void GetDueDateStatusOverdueWithDueDateTest()
        {
            var dueDate = new DateTime(2012, 11, 20);                       // 2012-11-20
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.Overdue;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, null, null, currentDate);

            Assert.AreEqual(expected, actual, "Overdue with DueDate");
        }

        [Test]
        public void GetDueDateStatusOverdueWithDueDateAndTimeTest()
        {
            var dueDate = new DateTime(2012, 11, 20);                       // 2012-11-20
            var startTime = new DateTime(2012, 11, 20, 10, 0, 0);           // 10:00:00
            var endTime = new DateTime(2012, 11, 20, 12, 0, 0);             // 12:00:00
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.Overdue;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, startTime, endTime, currentDate);

            Assert.AreEqual(expected, actual, "Overdue with DueDate & Time");
        }

        [Test]
        public void GetDueDateStatusOverdueWithDueDateAndStartTimeTest()
        {
            var dueDate = new DateTime(2012, 11, 20);                       // 2012-11-20
            var startTime = new DateTime(2012, 11, 20, 10, 0, 0);           // 10:00:00
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.Overdue;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, startTime, null, currentDate);

            Assert.AreEqual(expected, actual, "Overdue with DueDate & StartTime.");
        }

        [Test]
        public void GetDueDateStatusOverdueWithDueDateAndEndTimeTest()
        {
            var dueDate = new DateTime(2012, 11, 21);                       // 2012-11-21
            var endTime = new DateTime(2012, 11, 21, 10, 0, 0);             // 10:00:00
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.Overdue;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, null, endTime, currentDate);

            Assert.AreEqual(expected, actual, "Overdue with DueDate & EndTime.");
        }

        [Test]
        public void GetDueDateStatusReachDueDateWithoutTimeTest()
        {
            var dueDate = new DateTime(2012, 11, 21);                       // 2012-11-21
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.ReachDueDate;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, null, null, currentDate);

            Assert.AreEqual(expected, actual, "ReachDueDate without Time");
        }

        [Test]
        public void GetDueDateStatusReachDueDateWithTimeTest()
        {
            var dueDate = new DateTime(2012, 11, 21);                       // 2012-11-21
            var startTime = new DateTime(2012, 11, 21, 13, 0, 0);           // 13:00:00
            var endTime = new DateTime(2012, 11, 21, 13, 30, 0);            // 13:30:00
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.ReachDueDate;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, startTime, endTime, currentDate);

            Assert.AreEqual(expected, actual, "ReachDueDate with Time");
        }

        [Test]
        public void GetDueDateStatusReachDueTimeWithStartTimeAndEndTimeTest()
        {
            var dueDate = new DateTime(2012, 11, 21);                       // 2012-11-21
            var startTime = new DateTime(2012, 11, 21, 9, 0, 0);              // 09:00:00
            var endTime = new DateTime(2012, 11, 21, 11, 0, 0);               // 11:00:00
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.ReachDueTime;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, startTime, endTime, currentDate);

            Assert.AreEqual(expected, actual, "ReachDueTime with StartTime and EndTime");
        }

        [Test]
        public void GetDueDateStatusReachDueTimeWithStartTimeTest()
        {
            var dueDate = new DateTime(2012, 11, 21);                       // 2012-11-21
            var startTime = new DateTime(2012, 11, 21, 9, 0, 0);            // 09:00:00
            var currentDate = new DateTime(2012, 11, 21, 10, 54, 38);       // 2012-11-21 10:54:38
            var expected = DueDateStatus.ReachDueTime;
            var actual = InformationFormatter.GetDueDateStatus(dueDate, startTime, null, currentDate);

            Assert.AreEqual(expected, actual, "ReachDueTime with StartTime");
        }
        #endregion
    }
}
